package org.example.service;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.example.entity.Menus;
import org.example.entity.Roles;
import org.example.entity.User;
import org.example.exception.BusinessException;
import org.example.mapper.UserMapper;
import org.example.vo.UserDetail;
import org.example.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserService extends ServiceImpl<UserMapper, User> {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private FileService fileService;
    @Autowired
    private MenusServiceImpl menusService;
    @Autowired
    private RolesServiceImpl rolesService;

    public User findUserByAccount(String account) {
        return userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getAccount, account));
    }

    public void addUser(UserVo userVo) {
        User user = new User();
        User theuser = userMapper.selectOne(Wrappers.<User>lambdaQuery()
                .eq(User::getAccount, userVo.getAccount()));
        if (Objects.nonNull(theuser)) {
            throw new BusinessException("账户已存在，请重新输入");
        }
        user.setAccount(userVo.getAccount());
        user.setAvatar(userVo.getAvatar());
        user.setPassword(userVo.getPassword());
        user.setNickname(userVo.getNickname());
        user.setRole(userVo.getRole());
        int insert = userMapper.insert(user);
        log.info("{} user inserted", insert);
    }

    public void editUser(UserVo userVo) {
        User user = new User();
        User theuser = userMapper.selectOne(Wrappers.<User>lambdaQuery()
                .eq(User::getAccount, userVo.getAccount()));
        if (Objects.isNull(theuser)) {
            log.info("account {} not exist", userVo.getAccount());
        }
        user.setAccount(theuser.getAccount());
        user.setAvatar(userVo.getAvatar());
        if (StringUtils.isNotBlank(userVo.getPassword())) {
            user.setPassword(userVo.getPassword());
        }
        user.setNickname(userVo.getNickname());
        userMapper.update(user, Wrappers.<User>lambdaUpdate().eq(User::getAccount, userVo.getAccount()));
        if (!userVo.getAvatar().equals(theuser.getAvatar())) {
            fileService.deleteFile(theuser.getAvatar());
        }
    }

    public UserDetail findUserById(Long userId) {
        UserDetail userDetail = new UserDetail();
        User user = userMapper.selectById(userId);
        userDetail.setId(user.getId());
        userDetail.setAccount(user.getAccount());
        userDetail.setAvatar("http://localhost:8080" + user.getAvatar());
        userDetail.setRole(user.getRole());
        userDetail.setNickname(user.getNickname());
        List<Menus> menus = menusService.selectByRoleId(user.getRole());
        userDetail.setMenus(getRoots(menus));
        return userDetail;
    }

    private List<Menus> getRoots(List<Menus> menus) {
        List<Menus> root = menus.stream()
                .filter(x -> x.getParentId().equals(0))
                .toList();
        recursive(root, menus);
        return root;
    }

    private void recursive(List<Menus> roots, List<Menus> all) {
        for (Menus a : roots) {
            List<Menus> children = all.stream()
                    .filter(x -> x.getParentId().equals(a.getId()))
                    .toList();
            if (!CollectionUtils.isEmpty(children)) {
                a.setChildren(children);
                recursive(children, all);
            }
        }
    }

    public List<UserVo> userList() {
        List<User> users = userMapper.selectList(null);
        if (CollectionUtils.isEmpty(users)) {
            return new ArrayList<>();
        }
        List<Roles> roles = rolesService.allRole();
        Map<Long, String> roleMap = roles.stream()
                .collect(Collectors.toMap(Roles::getId, Roles::getRoleName));
        return users.stream()
                .map(x -> {
                    UserVo userVo = new UserVo();
                    userVo.setRoleName(roleMap.getOrDefault(x.getRole(), "-"));
                    userVo.setAvatar(x.getAvatar());
                    userVo.setAccount(x.getAccount());
                    userVo.setNickname(x.getNickname());
                    return userVo;
                }).toList();
    }

    public void deleteUsers(List<String> userAccounts) {
        if (CollectionUtils.isEmpty(userAccounts)) {
            return;
        }
        int delete = userMapper.delete(Wrappers.<User>lambdaQuery()
                .in(User::getAccount, userAccounts));
        log.info("{} users deleted", delete);
    }
}
